package com.coldworks.coldjoke.manager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.os.AsyncTask;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.coldworks.base.manager.BaseConfManager;
import com.coldworks.base.manager.BasePrefManager;
import com.coldworks.coldjoke.R;

public class NewTipsManager {
	protected final Logger log = LoggerFactory.getLogger(this.getClass());
	protected static NewTipsManager instance = null;

	public static NewTipsManager getInstance() {
		if (instance == null) {
			synchronized (NewTipsManager.class) {
				if (instance == null) {
					instance = new NewTipsManager();
				}
			}
		}
		return instance;
	}

	protected NewTipsManager() {
	}

	public void create(Context context) {
		try {
		} catch (Exception e) {
			log.error("", e);
		}
	}

	// TipsEvents会决定当一个事件发生时有多少tips要被关联启动
	public enum TipsShowEvent {
		NULL(TipsType.VERSION_ONCE, null); // 第一次提示发现页new

		protected final Logger log = LoggerFactory.getLogger(this.getClass());
		private TipsType tipsType; // 当前event对应的显示类型
		private String tipsKey; // 如果显示类型是TipsType.VERSION_ONCE,那么此值非空，用来检测是否已经显示过该类型tips
		private Boolean tipsEnable; // 当前是否允许tips显示

		private TipsShowEvent(TipsType tipsType, String tipsKey) {
			this.tipsType = tipsType;
			this.tipsKey = tipsKey;
			this.tipsEnable = false;
		}

		public TipsType getTipsType() {
			return tipsType;
		}

		public boolean isShowEnable() {
			return tipsEnable;
		}

		public void setShowEnable(Context context, int versionCode) {
			switch (this.tipsType) {
			case VERSION_ONCE:
				if (BasePrefManager.getInstance().getIntFromPrefs(context,
						this.tipsKey, 0) == versionCode) {
					this.tipsEnable = false;
					log.info("" + this.name() + ":no twice");
				} else {
					this.tipsEnable = true;
					log.info("" + this.name() + ":enable");
				}
				break;
			case ACTIVITY_ONCE:
				this.tipsEnable = true;
				break;
			case EACH_TIME:
				this.tipsEnable = true;
				break;
			}
		}

		public void setShowDisable(Context context, int versionCode) {
			switch (this.tipsType) {
			case VERSION_ONCE:
				this.tipsEnable = false;
				BasePrefManager.getInstance().setIntToPrefs(context,
						this.tipsKey, versionCode);
				log.info("" + this.name() + ":disable");
				break;
			case ACTIVITY_ONCE:
				this.tipsEnable = false;
				break;
			case EACH_TIME:
				this.tipsEnable = true;
				break;
			}
		}
	}

	public static enum TipsHideEvent {
	}

	// TipsId用于寻址Node树中的一个Node
	public static enum TipsId {
	}

	// TipsType会决定当TipsEvents事件发生时,按什么规则决定是否显示或隐藏new标签
	private static enum TipsType {
		VERSION_ONCE, // 此版本的第一次
		ACTIVITY_ONCE, // 此生命周期的第一次
		EACH_TIME; // 每一次
	}

	// 用TipsNode搭建一棵树，這樣就可以聯動了
	private class TipsNode {
		private TipsNode parent;
		private List<TipsNode> children;
		private RelativeLayout tipsLayout;
		private ImageView tipsView;

		public TipsNode(TipsNode parent, RelativeLayout tipsLayout,
				ImageView tipsView) {
			this.parent = parent;
			if (parent != null) {
				parent.addChild(this);
			}
			this.children = new ArrayList<TipsNode>();
			this.tipsLayout = tipsLayout;
			this.tipsView = tipsView;
		}

		public RelativeLayout getTipsLayout() {
			ViewGroup viewParent = (ViewGroup) this.tipsLayout.getParent();
			if (viewParent != null) {
				viewParent.removeView(this.tipsLayout);
			}
			return this.tipsLayout;
		}

		public void addChild(TipsNode child) {
			this.children.add(child);
		}

		public List<TipsNode> getChildren() {
			return children;
		}

		public boolean isVisible() {
			return this.tipsLayout.getVisibility() == View.VISIBLE;
		}

		public void setInVisible() {
			this.tipsView.setVisibility(View.INVISIBLE);
		}

		public void setVisible() {
			this.tipsView.setVisibility(View.VISIBLE);
		}

		public void show(Context context, TipsShowEvent tse) {
			if (tse.isShowEnable()) {
				this.setVisible();
				if (this.parent != null) {
					this.parent.show(context, tse);
				}
				tse.setShowDisable(context, BaseConfManager.getInstance()
						.getVersionCode(context));
				log.info("" + tse.name() + ":showing");
			} else {
				log.info("" + tse.name() + ":disable");
			}
		}

		public void hide(boolean loveBrother) {
			if (!this.isVisible()) {
				return;
			}
			this.setInVisible();
			if (this.parent == null) {
				return;
			}
			if (loveBrother) {
				boolean allBrotherHide = true;
				for (TipsNode brothers : this.parent.getChildren()) {
					if (brothers.isVisible()) {
						allBrotherHide = false;
						break;
					}
				}
				if (allBrotherHide) {
					this.parent.hide(loveBrother);
				}
			} else {
				this.parent.hide(loveBrother);
			}
		}
	}

	private Map<TipsShowEvent, TipsId> tipsShowEventMap = new HashMap<TipsShowEvent, TipsId>();
	private Map<TipsHideEvent, TipsId> tipsHideEventMap = new HashMap<TipsHideEvent, TipsId>();
	private Map<TipsId, TipsNode> tipsMap = new HashMap<TipsId, TipsNode>();

	protected TipsNode createNode(Context context, TipsNode parents, TipsId ti,
			TipsShowEvent[] tse, TipsHideEvent[] the) {
		RelativeLayout newTipsLayout = new RelativeLayout(context);
		newTipsLayout.setLayoutParams(new RelativeLayout.LayoutParams(
				ViewGroup.LayoutParams.MATCH_PARENT,
				ViewGroup.LayoutParams.MATCH_PARENT));
		ImageView newTipsView = new ImageView(context);
		newTipsView.setImageResource(R.drawable.new_tips);
		RelativeLayout.LayoutParams bevlp = new RelativeLayout.LayoutParams(
				ViewGroup.LayoutParams.WRAP_CONTENT,
				ViewGroup.LayoutParams.WRAP_CONTENT);
		bevlp.topMargin = 2;
		bevlp.rightMargin = 2;
		bevlp.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
		bevlp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
		newTipsView.setLayoutParams(bevlp);
		newTipsView.setVisibility(View.INVISIBLE);
		newTipsLayout.addView(newTipsView);
		TipsNode newNode = new TipsNode(parents, newTipsLayout, newTipsView);
		this.tipsMap.put(ti, newNode);
		for (TipsShowEvent one : tse) {
			this.tipsShowEventMap.put(one, ti);
		}
		for (TipsHideEvent one : the) {
			this.tipsHideEventMap.put(one, ti);
		}
		return newNode;
	}

	public RelativeLayout getTipsLayout(TipsId ti) {
		TipsNode node = tipsMap.get(ti);
		if (node != null) {
			return node.getTipsLayout();
		}
		return null;
	}

	public void tryShowingTips(final Context context, final TipsShowEvent tse) {
		new AsyncTask<Void, Void, TipsNode>() {
			@Override
			protected TipsNode doInBackground(Void... arg0) {
				TipsId tipsId = NewTipsManager.this.tipsShowEventMap.get(tse);
				return NewTipsManager.this.tipsMap.get(tipsId);
			}

			@Override
			protected void onPostExecute(TipsNode theOne) {
				if (theOne == null) {
					return;
				}
				theOne.show(context, tse);
			}
		}.execute();
	}

	public void tryHidingTips(final TipsHideEvent the, final boolean loveBrother) {
		new AsyncTask<Void, Void, TipsNode>() {
			@Override
			protected TipsNode doInBackground(Void... arg0) {
				TipsId tipsId = NewTipsManager.this.tipsHideEventMap.get(the);
				return NewTipsManager.this.tipsMap.get(tipsId);
			}

			@Override
			protected void onPostExecute(TipsNode theOne) {
				if (theOne == null) {
					return;
				}
				theOne.hide(loveBrother);
			}
		}.execute();
	}
}
